﻿using JNPF.Utils;
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Linq;
using System.Threading.Tasks;

namespace JNPF.Data.Util
{
    public static class PageHelper
    {
        public static PageResult<T> GetPageResult<T>(this IQueryable<T> source, PageInput pageInput)
        {
            var count = source.Count();
            if (!string.IsNullOrEmpty(pageInput.sidx))
                source = pageInput.sord.ToLower() == "asc" ? source.OrderBy(pageInput.sidx) : source.OrderByDescending(pageInput.sidx);
            source = source.Skip((pageInput.currentPage - 1) * pageInput.pageSize).Take(pageInput.pageSize);
            var list = source.ToList();
            return new PageResult<T> { list = list, pagination = new PageOutput() { currentPage = pageInput.currentPage, pageSize = pageInput.pageSize, total = count } };
        }
        public static async Task<PageResult<T>> GetPageResultAsync<T>(this IQueryable<T> source, PageInput pageInput)
        {
            var count = await source.CountAsync();
            if (!string.IsNullOrEmpty(pageInput.sidx))
                source = pageInput.sord.ToLower() == "asc" ? source.OrderBy(pageInput.sidx) : source.OrderByDescending(pageInput.sidx);
            source = source.Skip((pageInput.currentPage - 1) * pageInput.pageSize).Take(pageInput.pageSize);
            var list = await source.ToListAsync();
            return new PageResult<T> { list = list, pagination = new PageOutput() { currentPage = pageInput.currentPage, pageSize = pageInput.pageSize, total = count } };
        }
        public static List<T> GetPageList<T>(this IQueryable<T> source, PageInput pageInput)
        {
            if (!string.IsNullOrEmpty(pageInput.sidx))
                source = pageInput.sord.ToLower() == "asc" ? source.OrderBy(pageInput.sidx) : source.OrderByDescending(pageInput.sidx);
            source = source.Skip((pageInput.currentPage - 1) * pageInput.pageSize).Take(pageInput.pageSize);
            return source.ToList();
        }
        public static async Task<List<T>> GetPageListAsync<T>(this IQueryable<T> source, PageInput pageInput)
        {
            if (!string.IsNullOrEmpty(pageInput.sidx))
                source = pageInput.sord.ToLower() == "asc" ? source.OrderBy(pageInput.sidx) : source.OrderByDescending(pageInput.sidx);
            source = source.Skip((pageInput.currentPage - 1) * pageInput.pageSize).Take(pageInput.pageSize);
            return await source.ToListAsync();
        }
        public static PageResult<T> GetPageResult<T>(this IDatabase db, PageInput pageInput, string sql, DbParameter[] param = null) where T : class, new()
        {
            var multipleSql = DbSqlBuilder.QueryPageSql(pageInput, sql, db.dbContext.dbType);
            var count = db.ExecuteScalar(multipleSql["sqlCount"].ToString(), param);
            var list = db.GetListSql<T>(multipleSql["sqlText"].ToString());
            return new PageResult<T> { list = list, pagination = new PageOutput() { currentPage = pageInput.currentPage, pageSize = pageInput.pageSize, total = count.ToInt() } };
        }
        public static async Task<PageResult<T>> GetPageResultAsync<T>(this IDatabase db, PageInput pageInput, string sql, DbParameter[] param = null) where T : class, new()
        {
            var multipleSql = DbSqlBuilder.QueryPageSql(pageInput, sql, db.dbContext.dbType);
            var count = await db.ExecuteScalarAsync(multipleSql["sqlCount"].ToString(), param);
            var list = await db.GetListSqlAsync<T>(multipleSql["sqlText"].ToString(), param);
            return new PageResult<T> { list = list, pagination = new PageOutput() { currentPage = pageInput.currentPage, pageSize = pageInput.pageSize, total = count.ToInt() } };
        }
        public static List<T> GetPageList<T>(this IDatabase db, PageInput pageInput, string sql, DbParameter[] param = null) where T : class, new()
        {
            var multipleSql = DbSqlBuilder.QueryPageSql(pageInput, sql, db.dbContext.dbType);
            return db.GetListSql<T>(multipleSql["sqlText"].ToString());
        }
        public static async Task<List<T>> GetPageListAsync<T>(this IDatabase db, PageInput pageInput, string sql, DbParameter[] param = null) where T : class, new()
        {
            var multipleSql = DbSqlBuilder.QueryPageSql(pageInput, sql, db.dbContext.dbType);
            return await db.GetListSqlAsync<T>(multipleSql["sqlText"].ToString());
        }


        public static PageResult GetPageResult(this IDatabase db, PageInput pageInput, string sql, DbParameter[] param = null)
        {
            var multipleSql = DbSqlBuilder.QueryPageSql(pageInput, sql, db.dbContext.dbType);
            var count = db.ExecuteScalar(multipleSql["sqlCount"].ToString(), param);
            var list = db.GetTableSql(multipleSql["sqlText"].ToString());
            return new PageResult { list = list, pagination = new PageOutput() { currentPage = pageInput.currentPage, pageSize = pageInput.pageSize, total = count.ToInt() } };
        }
        public static async Task<PageResult> GetPageResultAsync(this IDatabase db, PageInput pageInput, string sql, DbParameter[] param = null)
        {
            var multipleSql = DbSqlBuilder.QueryPageSql(pageInput, sql, db.dbContext.dbType);
            var count = await db.ExecuteScalarAsync(multipleSql["sqlCount"].ToString(), param);
            var list = await db.GetTableSqlAsync(multipleSql["sqlText"].ToString(), param);
            return new PageResult { list = list, pagination = new PageOutput() { currentPage = pageInput.currentPage, pageSize = pageInput.pageSize, total = count.ToInt() } };
        }
        public static DataTable GetPageData(this IDatabase db, PageInput pageInput, string sql, DbParameter[] param = null)
        {
            var multipleSql = DbSqlBuilder.QueryPageSql(pageInput, sql, db.dbContext.dbType);
            return db.GetTableSql(multipleSql["sqlText"].ToString());
        }
        public static async Task<DataTable> GetPageDataAsync(this IDatabase db, PageInput pageInput, string sql, DbParameter[] param = null)
        {
            var multipleSql = DbSqlBuilder.QueryPageSql(pageInput, sql, db.dbContext.dbType);
            return await db.GetTableSqlAsync(multipleSql["sqlText"].ToString(), param);
        }

        public static async Task<PageResult<Dictionary<string, object>>> GetPageDictionaryAsync(this IDatabase db, PageInput pageInput, string sql, DbParameter[] param = null)
        {
            var multipleSql = DbSqlBuilder.QueryPageSql(pageInput, sql, db.dbContext.dbType);
            var count = await db.ExecuteScalarAsync(multipleSql["sqlCount"].ToString(), param);
            var list = await db.GetPageDictionaryAsync(multipleSql["sqlText"].ToString(), param);
            return new PageResult<Dictionary<string, object>> { list = list, pagination = new PageOutput() { currentPage = pageInput.currentPage, pageSize = pageInput.pageSize, total = count.ToInt() } };
        }
    }
}
